package live.jialing.sip.base.rest;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import live.jialing.core.context.LoginAccountContext;
import live.jialing.core.exception.RestException;
import live.jialing.core.web.controller.SimpleBaseRestController;
import live.jialing.core.web.paging.DataTableReturnObject;
import live.jialing.core.web.paging.PageUtil;
import live.jialing.sip.base.dict.ClassCategoryEnum;
import live.jialing.sip.base.domain.School;
import live.jialing.sip.base.domain.Squad;
import live.jialing.sip.base.domain.Student;
import live.jialing.sip.base.domain.Teacher;
import live.jialing.sip.base.service.*;
import live.jialing.sip.base.util.SchoolUtil;
import live.jialing.sip.base.vo.ClassVO;
import live.jialing.sip.base.vo.GradeVO;
import live.jialing.structure.domain.Department;
import live.jialing.structure.domain.Employee;
import live.jialing.structure.domain.Position;
import live.jialing.structure.service.DepartmentService;
import live.jialing.structure.service.EmployeeService;
import live.jialing.util.general.Collections3;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Page;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.groupingBy;

/**
 * 学校接口
 *
 * 查询学校／分页查询   get /schools
 * 新增    post /schools
 * 删除    delete /schools/{id}
 * 修改    put  /schools/{id}
 * 查询制定ID的详情  get /schools/{id}
 *
 *
 * 学校部门
 * 新增部门   post     /schools/{schoolId}/depts
 * 删除部门   delete /schools/{schoolId}/depts/{deptId}
 *
 *
 *
 *
 */
@RestController
@RequestMapping(value = "/schools")
public class SchoolRestController extends SimpleBaseRestController<School, Long> {

    private static Logger logger = LoggerFactory.getLogger(SchoolRestController.class);

    // 学校
    @Resource
    private SchoolService schoolService;

    // 年级
    @Resource
    private GradeService gradeService;

    // 班级
    @Resource
    private ClassService classService;

    // 部门
    @Resource
    private DepartmentService departmentService;

    // 老师
    @Resource
    private TeacherService teacherService;

    // 学生
    @Resource
    private StudentService studentService;

    // 员工
    @Resource
    private EmployeeService employeeService;

    @Override
    public SchoolService getService() {
        return this.schoolService;
    }

    /**
     * 设置学校校长（单个）
     *
     * @param schoolId   学校ID
     * @param employeeId 员工
     */
    @RequestMapping(value = "/{schoolId}/masters", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public void setupSchoolMaster(@PathVariable("schoolId") Long schoolId, Long employeeId) {

        org.apache.commons.lang3.Validate.notNull(employeeId, "职工不能为空！");
        schoolService.setupSchoolMaster(schoolId, employeeId);
    }

    /**
     * 取消学校校长（单个）
     *
     * @param schoolId   学校ID
     * @param employeeId 员工ID
     */
    @RequestMapping(value = "/{schoolId}/masters/{employeeId}", method = RequestMethod.DELETE, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public void unsetupSchoolMaster(@PathVariable("schoolId") Long schoolId, @PathVariable("employeeId") Long employeeId) {

        org.apache.commons.lang3.Validate.notNull(schoolId, "学校不能为空！");
        org.apache.commons.lang3.Validate.notNull(employeeId, "职工不能为空！");
        schoolService.unSetupSchoolMaster(schoolId, employeeId);
    }

    /**
     * 设置学校领导（多个）
     *
     * @param schoolId    学校ID
     * @param employeeIds 员工集合
     */
    @RequestMapping(value = "/{schoolId}/leaders", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public void setupSchoolLeader(@PathVariable("schoolId") Long schoolId, List<Long> employeeIds) {

        org.apache.commons.lang3.Validate.notEmpty(employeeIds, "教职工不能为空！");
        schoolService.setupSchoolLeader(schoolId, employeeIds);
    }

    /**
     * 取消学校领导（单个）
     *
     * @param schoolId   学校ID
     * @param employeeId 职工ID
     */
    @RequestMapping(value = "/{schoolId}/leaders/{employeeId}", method = RequestMethod.DELETE, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public void unsetupSchoolLeader(@PathVariable("schoolId") Long schoolId, @PathVariable("employeeId") Long employeeId) {

        org.apache.commons.lang3.Validate.notNull(schoolId, "学校不能为空！");
        org.apache.commons.lang3.Validate.notNull(employeeId, "职工不能为空！");
        schoolService.updateSchoolLeader(schoolId, employeeId);
    }

    /**
     * 设置年级组组长
     *
     * @param schoolId 学校ID
     * @param grade    入学年份
     * @param category 班级类型
     * @param employee 职工
     */
    @RequestMapping(value = "/{schoolId}/grades/{grade}/{classCategory}/masters", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public void setupGradeMaster(@PathVariable("schoolId") Long schoolId, @PathVariable("grade") Integer grade,
                                 @PathVariable("classCategory") ClassCategoryEnum category, Employee employee) {

        org.apache.commons.lang3.Validate.notNull(employee, "教职工参数为空！");
        gradeService.setupGradeMaster(schoolId, grade, category, employee.getId());
    }

    /**
     * 当前用户获取所在的学校
     *
     * @param loginAccountContext 当前用户上下文
     * @return 学校集合
     */
    @RequestMapping(value = "/my", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public List<School> getMySchool(LoginAccountContext loginAccountContext) {

        long userId = loginAccountContext.currentLoginUserId();

        Map<String, Object> searchParams = Maps.newTreeMap();
        searchParams.put("EQ_employees.user.id", userId);
        return schoolService.findAll(searchParams, null);
    }

    /**
     * 当前用户获取在指定学校中的所在部门
     *
     * @param schoolId            学校ID
     * @param loginAccountContext 当前用户上下文
     * @return 部门集合
     */
    @RequestMapping(value = "/{schoolId}/departments/my", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public List<Department> getMyDepartmentByOrg(@PathVariable("schoolId") Long schoolId, LoginAccountContext loginAccountContext) {

        long userId = loginAccountContext.currentLoginUserId();

        Map<String, Object> searchParams = Maps.newTreeMap();
        searchParams.put("EQ_company.id", schoolId);
        searchParams.put("EQ_employees.id", userId);
        return departmentService.findAll(searchParams, null);
    }

    /**
     * 设置班主任
     *
     * @param schoolId   学校ID
     * @param classId    班级ID
     * @param employeeId 员工
     */
    @RequestMapping(value = "/{schoolId}/classes/{classId}/master", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public void setupClassMaster(@PathVariable("schoolId") Long schoolId, @PathVariable("classId") Long classId, Long employeeId) {

        org.apache.commons.lang3.Validate.notNull(employeeId, "员工参数为空！");
        teacherService.setupClassMaster(schoolId, classId, employeeId);
    }

    /**
     * 设置科任老师
     *
     * @param schoolId   学校ID
     * @param classId    班级ID
     * @param employeeId 员工
     * @param subject    科目代码
     * @see live.jialing.sip.base.dict.SchoolSubjectEnum
     */
    @RequestMapping(value = "/{schoolId}/classes/{classId}/teacher", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public void setupClassMaster(@PathVariable("schoolId") Long schoolId, @PathVariable("classId") Long classId, Long employeeId, String subject) {

        org.apache.commons.lang3.Validate.notNull(employeeId, "员工参数为空！");
        org.apache.commons.lang3.Validate.notBlank(subject, "科目参数为空！");
        teacherService.setupClassTeacher(schoolId, classId, employeeId, subject);
    }

    /**
     * 获取老师所在的所有班级
     *
     * @param schoolId  学校ID
     * @param teacherId 老师ID
     * @return 班级集合
     */
    @RequestMapping(value = "/{schoolId}/classes/my", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public List<Squad> findSquadByTeacher(@PathVariable("schoolId") Long schoolId, Long teacherId) {

        org.apache.commons.lang3.Validate.notNull(schoolId, "学校不能为空！");
        org.apache.commons.lang3.Validate.notNull(teacherId, "员工不能为空！");
        return classService.findClassByTeacher(schoolId, teacherId);
    }

    /**
     * 获取指定教职工可见的班级
     * <p>
     * 校长看全校、年级主任看年级、班主任/老师看本班
     * </p>
     *
     * @param schoolId   学校id
     * @param employeeId 员工id
     * @return [{"category":"H","inYear":"2006","name":"高2016级","classes":[{"category":"H","id":"1","name":"高2016级1班"}]}]
     */
    @RequestMapping(value = "/{schoolId}/classes/visible", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public List<GradeVO> findSquadByEmployee(@PathVariable("schoolId") Long schoolId, Long employeeId) {

        org.apache.commons.lang3.Validate.notNull(schoolId, "学校不能为空！");
        org.apache.commons.lang3.Validate.notNull(employeeId, "员工不能为空！");

        // 获取员工能够查看的班级，校长看全校、年级主任看年级、班主任/老师看本班
        List<Squad> classes = classService.findClassByEmployee(schoolId, employeeId);
        if (Collections3.isEmpty(classes)) {
            return Lists.newArrayList();
        }

        List<GradeVO> gradeVOs = Lists.newArrayList();
        // 根据班级类型分组
        Map<ClassCategoryEnum, List<Squad>> squadByCategory = classes.stream().collect(groupingBy(Squad::getCategory));
        squadByCategory.forEach((category, list) -> {
            // 根据入学年份分组
            Map<Integer, List<Squad>> squadByGrade = list.stream().collect(groupingBy(Squad::getGrade));
            squadByGrade.forEach((grade, list2) -> {
                GradeVO dto = new GradeVO();
                dto.setInYear(grade);
                dto.setName(SchoolUtil.gradeName(category, grade));
                dto.setCategory(category);
                dto.setClasses(list2.stream().map(c -> {
                    ClassVO vo = new ClassVO();
                    vo.setId(c.getId());
                    vo.setName(SchoolUtil.className(c.getCategory(), c.getGrade(), c.getNum(), c.getAlias()));
                    vo.setCategory(c.getCategory());
                    return vo;
                }).collect(Collectors.toList()));
            });
        });

        return gradeVOs;
    }

    // 部门

    /**
     * 获取指定学校的所有部门
     *
     * @param schoolId 学校ID
     * @return 部门集合
     */
    @RequestMapping(value = "/{schoolId}/departments", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public List<Department> findAllDepartment(@PathVariable("schoolId") Long schoolId) {

        if (schoolId == null || schoolId.longValue() < 1) {
            throw new RestException("学校ID不正确！");
        }

        return departmentService.findDepartmentByOrg(schoolId.longValue());
    }

    /**
     * 设置/关联部门的成员
     *
     * @param departmentId 部门id
     * @param employees    [{"id":"1"},{"id":"2"},{"id":"3"}]
     */
    @RequestMapping(value = "/{schoolId}/departments/{deptId}/teachers", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_UTF8_VALUE, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public void relationEmployee(@PathVariable("deptId") Long departmentId, @RequestBody List<Employee> employees) {

        if (Collections3.isEmpty(employees)) {
            return;
        }

        departmentService.relationEmployee(departmentId, employees.stream().map(t -> t.getId()).distinct().collect(Collectors.toList()));
    }

    // 用户组

    // 员工

    /**
     * TODO 教职工批量导入（新增）
     */


    /**
     * 分页获取指定学校的员工
     *
     * @param schoolId 学校ID
     * @param request
     * @param pageUtil
     * @return 员工的分页集合
     * @see live.jialing.structure.domain.Employee
     */
    @RequestMapping(value = "/{schoolId}/employees", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public DataTableReturnObject findPageTeacher(@PathVariable("schoolId") Long schoolId, HttpServletRequest request, PageUtil pageUtil) {

        if (schoolId == null || schoolId.longValue() < 1) {
            throw new RestException("学校ID不正确！");
        }

        Map<String, Object> searchParams = this.getSearchParams(request);
        searchParams.put("EQ_company.id", schoolId);
        Page<Employee> page = employeeService.findPage(searchParams, pageUtil.getPageNumber(), pageUtil.getiDisplayLength().intValue(), null);
        return pageUtil.returnObject(page);
    }

    /**
     * 获取指定学校-部门的员工
     *
     * @param schoolId     学校ID
     * @param departmentId 部门ID
     * @param request
     * @return 员工的集合
     */
    @RequestMapping(value = "/{schoolId}/departments/{deptId}/employees", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public List<Employee> findPageTeacherByDept(@PathVariable("schoolId") Long schoolId,
                                                @PathVariable("deptId") Long departmentId, HttpServletRequest request) {

        if (schoolId == null || schoolId.longValue() < 1 || departmentId == null || departmentId.longValue() < 1) {
            throw new RestException("学校ID或部门ID不正确！");
        }

        List<Position> positions = departmentService.findEmployeeByDepartment(schoolId, departmentId);
        if (Collections3.isEmpty(positions)) {
            return Lists.newArrayList();
        }

        return employeeService.findByPKs(positions.stream().map(p -> p.getEmployeeId()).distinct().collect(Collectors.toList()));
    }

    // 年级

    /**
     * 获取指定学校的所有在读年级
     *
     * @param schoolId 学校id
     * @return 年级集合
     */
    @RequestMapping(value = "/{schoolId}/grades", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public List<GradeVO> findAllGrade(@PathVariable("schoolId") Long schoolId) {

        if (schoolId == null || schoolId.longValue() < 1) {
            throw new RestException("学校ID不正确！");
        }

        return schoolService.findOnlineGrade(schoolId.longValue());
    }

    // 班级

    /**
     * 检索指定学校的班级
     *
     * @param schoolId 学校id
     * @return 班级的分页集合
     * @see live.jialing.sip.base.domain.Squad
     */
    @RequestMapping(value = "/{schoolId}/classes", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public DataTableReturnObject findPageClassBySchool(@PathVariable("schoolId") Long schoolId, HttpServletRequest request, PageUtil pageUtil) {

        if (schoolId == null || schoolId.longValue() < 1) {
            throw new RestException("学校ID不正确！");
        }

        Map<String, Object> searchParams = this.getSearchParams(request);
        searchParams.put("EQ_school.id", schoolId);
        Page<Squad> objs = classService.findPage(searchParams, pageUtil.getPageNumber(), pageUtil.getiDisplayLength().intValue(), null);
        return pageUtil.returnObject(objs);
    }

    /**
     * 检索指定学校、年级的所有班级
     *
     * @param schoolId 学校ID
     * @param grade    年级，入学年份
     * @return 班级的分页集合
     * @see live.jialing.sip.base.domain.Squad
     */
    @RequestMapping(value = "/{schoolId}/grades/{grade}/classes", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public DataTableReturnObject findClassByGrade(@PathVariable("schoolId") Long schoolId, @PathVariable("grade") Integer grade,
                                                  HttpServletRequest request, PageUtil pageUtil) {

        if (schoolId == null || schoolId.longValue() < 1) {
            throw new RestException("学校ID不正确！");
        }

        Map<String, Object> searchParams = this.getSearchParams(request);
        searchParams.put("EQ_school.id", schoolId);
        searchParams.put("EQ_grade", grade);
        Page<Squad> objs = classService.findPage(searchParams, pageUtil.getPageNumber(), pageUtil.getiDisplayLength().intValue(), null);
        return pageUtil.returnObject(objs);
    }


    // 学生

    // TODO 导入学生

    /**
     * 分页获取指定学校的所有在读学生
     *
     * @param schoolId 学校ID
     * @param request
     * @param pageUtil 分页参数
     * @return 学生的分页集合
     * @see live.jialing.sip.base.domain.Student
     */
    @RequestMapping(value = "/{schoolId}/students", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public DataTableReturnObject findPageOnlineStudent(@PathVariable("schoolId") Long schoolId, HttpServletRequest request, PageUtil pageUtil) {

        if (schoolId == null || schoolId.longValue() < 1) {
            throw new RestException("学校ID不正确！");
        }

        Map<String, Object> searchParams = this.getSearchParams(request);
        searchParams.put("EQ_school.id", schoolId);
        Page<Student> page = studentService.findPage(searchParams, pageUtil.getPageNumber(), pageUtil.getiDisplayLength().intValue(), null);
        return pageUtil.returnObject(page);
    }

    /**
     * 获取班级中的学生
     *
     * @param schoolId 学校id
     * @param classId  班级id
     * @param request
     * @param pageUtil 分页参数
     * @return 学生的分页集合
     * @see live.jialing.sip.base.domain.Student
     */
    @RequestMapping(value = "/{schoolId}/classes/{classId}/students", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public DataTableReturnObject findStudentByClass(@PathVariable("schoolId") Long schoolId, @PathVariable("classId") Long classId,
                                                    HttpServletRequest request, PageUtil pageUtil) {

        if (schoolId == null || schoolId.longValue() < 1 || classId == null || classId.longValue() < 1) {
            throw new RestException("学校ID或班级ID不正确！");
        }

        Map<String, Object> searchParams = this.getSearchParams(request);
        searchParams.put("EQ_school.id", schoolId);
        searchParams.put("EQ_squad.id", classId);
        Page<Student> page = studentService.findPage(searchParams, pageUtil.getPageNumber(), pageUtil.getiDisplayLength().intValue(), null);
        return pageUtil.returnObject(page);
    }

    /**
     * 获取指定班级的所有老师：班主任、任课老师
     *
     * @param schoolId 学校ID
     * @param classId  班级ID
     * @return 老师集合
     */
    @RequestMapping(value = "/{schoolId}/classes/{classId}/teachers", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public List<Teacher> findTeacher(@PathVariable("schoolId") Long schoolId, @PathVariable("classId") Long classId) {

        return teacherService.findTeacherByClass(classId);
    }

}
